#include <iostream>
#include <exception>
#include <common.h>

using namespace std;

namespace EXCEPTION1_DAY16
{
    void func1(int x)
    {
        if (x == 0) {
            throw std::invalid_argument("x不能为0");
        } else if (x < 0) {
            throw std::out_of_range("x不能为负数");
        }
        else 
        {
            throw std::runtime_error("x不能为正数");
        }
    }

};

namespace EXCEPTION2_DAY16
{
    int divide(int a1, int a2)
    {
        if (a2 == 0)
        {
            throw "除数不能为0,Gui Yang Yang likes apple!";
        }

        return a1 / a2;
    }
};

namespace EXCEPTION3_DAY16
{
    class MyException : public exception
    {
        private:
            const char *msg_;
        public:
            MyException(const char *messages) : msg_(messages) {cout << "自定义类的构造函数!" << endl;}
            const char * what() const noexcept override
            {
                return msg_;
            }
    };

    void myexception_test()
    {
        cout << "Throw before!" << endl;
        throw MyException("这是一个自定义异常!");
        cout << "Throw after!" << endl;
    }

};

namespace EXCEPTION4_DAY16
{
    void func2()
    {
        try
        {
            cout << "func2 try1" << endl;
            throw runtime_error("Exception_ptr 异常抛出测试！");
            cout << "func2 try2" << endl;
        }
        catch(...) 
        {
            cout << "func2 catch1" << endl;
            std::exception_ptr p = std::current_exception();
            cout << "func2 catch2" << endl;
            std::rethrow_exception(p);
            cout << "func2 catch3" << endl;
        }
        
    }
};




int main() {

    {   __LOG__("多异常抛出");
        using namespace EXCEPTION1_DAY16;
        try
        {
            func1(2);
        }
        catch(std::invalid_argument& e)
        {
            std::cout << "invalid argument: " << e.what() << std::endl;
        }
        catch (std::out_of_range& e)
        {
            std::cout << "out of range: " << e.what() << std::endl;
        }
        catch (std::runtime_error& e)
        {
            std::cout << "exception: " << e.what() << std::endl;
        }

    }

    {
        __LOG__("直接抛出异常");
        using namespace EXCEPTION2_DAY16;

        int a = 10;
        int b = 0;
        int result = 0;
        try
        {
            result = divide(a,b);
            cout << "结果是：" << result << endl;
        }
        catch (const char *e)
        {
            cerr << "发生错误：" << e << endl;

        }

    }
    
    {
        __LOG__("自定义异常");
        using namespace EXCEPTION3_DAY16;

        try
        {
            cout << "异常检测" << endl;
            myexception_test();
            cout << "异常检测后" << endl;
        }
        catch(MyException e)
        {
            std::cerr << e.what() << '\n';
        }
        

    }

    {
        __LOG__("Exception_ptr异常");
        using namespace EXCEPTION4_DAY16;
        try
        {
            cout << "main try1" << endl;
            func2();
            cout << "main try2" << endl;
        }
        catch(const std::exception& e)
        {
            cout << "main catch1" << endl;
            std::cerr << e.what() << '\n';
            cout << "main catch2" << endl;
        }
        
    }
    
    return 0;
}






